<!--

    Copyright (c) 2012-2018 Red Hat, Inc.
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
    http://www.eclipse.org/legal/epl-v10.html

    Contributors:
      Red Hat, Inc. - initial API and implementation

-->
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta name="mobile-web-app-capable" content="yes">
    <title>Eclipse Che</title>
    <link rel="shortcut icon" href="/_app/favicon.ico"/>
    <link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet" type="text/css"/>

    <script type="text/javascript" language="javascript">

        /**This parameter is needed to define sdk mode.*/
        window.sdk = 1;

        /**
         * Base IDE object
         */

        window.IDE = {};

        /**
         * Initial configuration
         */

        window.IDE.config = {
            "restContext": "/api",
            "websocketContext": "/websocket"
        };

        /**
         * Event handlers
         */

        window.IDE.eventHandlers = {};

        window.IDE.eventHandlers.initializationFailed = function (message) {
            if (message) {
                var err = new Error(message);
                window.alert(err.stack);
            } else {
                window.alert("Unable to initialize IDE");
            }
        };

        var Loader = new function() {

            /*
             * Load keycloak settings
             */
            this.loadKeycloakSettings = function() {
                var msg = "Cannot load keycloak settings. This is normal for single-user mode.";
                
                try {
                    var request = new XMLHttpRequest();

                    request.onerror = request.onabort = function() {
                        console.error(msg);
                        Loader.startLoading();
                    };

                    request.onload = function() {
                        if (request.status == 200) {
                            Loader.injectKeycloakScript(JSON.parse(this.responseText));
                        } else {
                            console.error(msg);
                            Loader.startLoading();
                        }
                    };

                    var url = "/api/keycloak/settings";
                    request.open("GET", url, true);
                    request.send();
                } catch (e) {
                    console.error(msg, e);
                    Loader.startLoading();
                }
            };
            
            /*
             * Injects keycloak javascript
             */
            this.injectKeycloakScript = function(keycloakSettings) {
                var script = document.createElement("script");
                script.type = "text/javascript";
                script.language = "javascript";
                script.async = true;
                script.src = keycloakSettings['che.keycloak.js_adapter_url'];

                script.onload = function() {
                    Loader.initKeycloak(keycloakSettings);
                };
                
                script.onerror = script.onabort = function() {
                    console.error("Cannot load " + script.src);
                    Loader.startLoading();
                };
                                    
                document.head.appendChild(script);
            };

            /*
             * Initialize keycloak and load the IDE
             */
            this.initKeycloak = function(keycloakSettings) {
                function keycloakConfig() {
                  const theOidcProvider = keycloakSettings['che.keycloak.oidc_provider'];
                  if (!theOidcProvider) {
                      return {
                        url: keycloakSettings['che.keycloak.auth_server_url'],
                        realm: keycloakSettings['che.keycloak.realm'],
                        clientId: keycloakSettings['che.keycloak.client_id']
                      };
                    } else {
                      return {
                        oidcProvider: theOidcProvider,
                        clientId: keycloakSettings['che.keycloak.client_id']
                      };
                    }
                }
                var keycloak = Keycloak(keycloakConfig());
                
                window['_keycloak'] = keycloak;
                
                var useNonce;
                if (typeof keycloakSettings['che.keycloak.use_nonce'] === 'string') {
                  useNonce = keycloakSettings['che.keycloak.use_nonce'].toLowerCase() === 'true';
                }
                
                keycloak
                    .init({onLoad: 'login-required', checkLoginIframe: false, useNonce: useNonce})
                    .success(function(authenticated) {
                        Loader.startLoading();
                    })
                    .error(function () {
                        console.log('[Keycloak] Failed to initialize Keycloak');
                    });
            };

            /*
             * Show loader and load compilation-mapping.txt file to determine which IDE JavaScript file will be loaded
             */
            this.startLoading = function() {
                setTimeout(() => {
                    document.getElementById("ide-loader").style.opacity = 1;
                }, 1);

                setTimeout(() => {
                    window.parent.postMessage("show-ide", "*");
                }, 250);                

                var msg = "Cannot load compilation mappings";

                try {
                    var request = new XMLHttpRequest();

                    request.onerror = request.abort = function() {
                        console.error(msg);
                    };

                    request.onload = function() {
                        if (request.status == 200) {
                            Loader.determineIDEJavaScriptFileName(request.responseText);
                        } else {
                            console.error(msg);
                        }
                    };

                    var url = "/_app/compilation-mappings.txt?" + new Date().getTime();
                    request.open("GET", url, true);
                    request.send();
                } catch (e) {
                    console.error(msg, e);
                }
            };

            /*
             * Returns browser identifier for searching in compilation-mappings.txt
             *
             * Many years ago this method was copied from
             * https://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/rebind/UserAgentPropertyGenerator.java?r=9701
             */
            this.getBrowserIdentifier = function() {
                var userAgent = navigator.userAgent.toLowerCase();

                var makeVersion = function(result) {
                    return (parseInt(result[1]) * 1000) + parseInt(result[2]);
                };

                if (userAgent.includes('opera')) {
                    return 'opera';
                } else if (userAgent.includes('webkit')) {
                    return 'safari';
                } else if (userAgent.includes('msie')) {
                    if (document.documentMode >= 8) {
                        return 'ie8';
                    } else {
                        var result = /msie ([0-9]+)\\.([0-9]+)/.exec(userAgent);
                        if (result && result.length == 3) {
                            var v = makeVersion(result);
                            if (v >= 6000) {
                                return 'ie6';
                            }
                        }
                    }
                } else if (userAgent.includes('gecko')) {
                    return 'gecko1_8';
                }

                return 'unknown';
            };

            /*
             * Determine name of IDE JavaScript file
             */
            this.ideJavaScriptFileName = null;
            this.ideJavaScriptFileSize = 0;

            this.determineIDEJavaScriptFileName = function(compilationMappings) {
                try {
                    var browserIdentifier = Loader.getBrowserIdentifier();

                    var mappings = compilationMappings.split("\n");

                    var jsName = null;
                    var mobileUserAgent = null;
                    var userAgent = null;
                    var webideClientOS = null;

                    for (var i = 0; i < mappings.length; i++) {
                        if (mappings[i] === "") {
                            if (jsName && userAgent && browserIdentifier === userAgent.split(" ")[1]) {
                                Loader.ideJavaScriptFileName = jsName;
                                Loader.loadCompilationMappingsPropertiesFile();
                                return;
                            }

                            jsName = null;
                            mobileUserAgent = null;
                            userAgent = null;
                            webideClientOS = null;
                        }

                        if (mappings[i].endsWith(".cache.js")) {
                            jsName = mappings[i];
                        }

                        if (mappings[i].startsWith("mobile.user.agent ")) {
                            mobileUserAgent = mappings[i];
                        }

                        if (mappings[i].startsWith("user.agent ")) {
                            userAgent = mappings[i];
                        }

                        if (mappings[i].startsWith("webide.clientOs ")) {
                            webideClientOS = mappings[i];
                        }
                    }
                } catch (e) {
                    console.error(e);
                }

                // IDE java script file name is not determined or error has occurred. Inject `.nocache.js` script and that's it.
                Loader.injectIDEJavaScript();
            };

            /*
             * Load compilation-mappings.properties and determine content length of IDE java script.
             *
             * The file must be generated when compiling the IDE and have following format
             *    0D3AF216CC89C9E9AAAC979BDBD6B5DF.cache.js : 9490046
             *    8D20590E9A332A3AA0062EE99096933F.cache.js : 9493464
             */
            this.loadCompilationMappingsPropertiesFile = function() {
                var msg = "Unable to load compilation-mappings.properties";

                try {
                    var request = new XMLHttpRequest();

                    request.onerror = request.abort = function() {
                        console.error(msg);
                        Loader.injectIDEJavaScript();
                    };

                    request.onload = function() {
                        if (request.status == 200) {
                            Loader.determineIDEJavaScriptContentLength(request.responseText);
                        } else {
                            console.error(msg);
                            Loader.injectIDEJavaScript();
                        }
                    };

                    var url = "/_app/compilation-mappings.properties?" + new Date().getTime();
                    request.open("GET", url, true);
                    request.send();
                } catch (e) {
                    console.error(msg, e);
                    Loader.injectIDEJavaScript();
                }
            };

            /*
             * Determine IDE java script file size
             */
            this.determineIDEJavaScriptContentLength = function(compilationMappingsProperties) {
                var mappings = compilationMappingsProperties.split("\n");

                try {
                    for (var i = 0; i < mappings.length; i++) {
                        var parts = mappings[i].split(" : ");

                        if (parts[0] === Loader.ideJavaScriptFileName) {
                            Loader.ideJavaScriptFileSize = parseInt(parts[1]);
                            Loader.loadIDEJavaScript();
                        }
                    }
                } catch (e) {
                    console.error("Cannot determine size of IDE JavaScript", e);
                }
            };

            /*
             * Load content of IDE JavaScript
             */
            this.loadIDEJavaScript = function() {
                var msg = "Unable to load IDE JavaScript";

                try {
                    var request = new XMLHttpRequest();

                    request.onprogress = function(event) {
                        var percentComplete = event.loaded / Loader.ideJavaScriptFileSize * 100;
                        var rounded = Math.round(percentComplete);
                        if (rounded > 100) {
                            rounded = 100;
                        }

                        document.getElementById("ide-loader-progress-bar").style.width = rounded + "%";
                    };

                    request.onload = function() {
                        Loader.injectIDEJavaScript();
                    };

                    request.onerror = request.abort = function () {
                        console.error(msg);
                        Loader.injectIDEJavaScript();
                    };

                    request.open("GET", "/_app/" + Loader.ideJavaScriptFileName, true);
                    request.send();
                } catch (e) {
                    console.error(msg, e);
                    Loader.injectIDEJavaScript();
                }
            };

            /*
             * Injects IDE JavaScript
             */
            this.injectIDEJavaScript = function() {
                document.getElementById("ide-loader-progress-bar").style.width = "100%";

                var script = document.createElement("script");
                script.type = "text/javascript";
                script.language = "javascript";
                script.async = true;
                script.src = "/_app/_app.nocache.js";
                document.head.appendChild(script);
            };
        };

        setTimeout(() => {
            Loader.loadKeycloakSettings();
        }, 1);

    </script>

</head>

<body style="background-color: #21252b; transition: background-color 0.5s ease;">
<div id="ide-loader" style="position: fixed; width: 300px; height: 45px; left: 50%; top: 30%;
            margin-left: -150px; opacity: 0; transition: all 0.2s ease-in-out;">
    <div style="position: absolute; left: 0px; top: 0px; width: 300px; height: 30px;
          font-family: sans-serif; font-size: 14px;
          line-height: 30px; text-align: center; color: #a0a9b7;">Loading...</div>
    <div style="position: absolute; width: 300px; height: 15px; left: 0px; bottom: 0px;
            background-color: #202325; border: 1px solid #456594; box-sizing: border-box;">
        <div id="ide-loader-progress-bar" style="box-sizing: border-box; height: 100%; width: 0%;
            border: 1px solid #161819; background-color: #498fe1; transition: all 0.2s ease-in-out;" />
    </div>
</div>
</body>

</html>
